<?php
/**
 * 提取类相关信息
 */
class Trace{
	public static $funcs	= array();
	public static $classes	= array();

	public static $function	= array();
	public static $class	= array();
	public static $method	= array();

	public static $exts		= array();
	public static $ext		= array();

	// 获取用户自定义函数
	public static function get_user_funcs(){
		if(!empty(self::$funcs)){
			return self::$funcs;
		}
		$funcs = get_defined_functions();
		foreach($funcs['user'] as $function_name){
			$rf = new ReflectionFunction($function_name);
			$objParams = $rf->getParameters();
			$param_str_arr = array();
			if(!empty($objParams)){
				foreach($objParams as $param){
					$default = '';
					if($param->isOptional()){
						$default = $param->getDefaultValue();
						if(empty($default)){
							if(is_array($default)){
									$default = "array()";
								}else{
									if(is_numeric($default)){
										$default = '0';
									}else{
										$default = "''";
									}
								}
						}else{
							$default = htmlspecialchars(str_replace('Array(', 'array(', preg_replace('/\s+/i', '', $default)), ENT_QUOTES);
						}
					}
					$param_str_arr[] = '$'.$param->getName().($default === '' ? '' : ' = '.$default);
				}
			}
			self::$funcs[] = '<a href="./m.php?frm=system&mdl=debug&do=info&funcs=yes&fn='.$function_name.'#'.$function_name.'">'.$function_name.'('.implode(', ', $param_str_arr).')</a>';
		}
		return self::$funcs;
	}

	// 获取用户自定义类，可能比较耗时，请慎用
	public static function get_user_classes(){
		if(!empty(self::$classes)){
			return self::$classes;
		}
		self::$classes = array();
		$classes = get_declared_classes();
		foreach($classes  as $class){
			$rc = new ReflectionClass($class);
			if($rc->isUserDefined()){
				$class_name = $rc->getName();
				self::$classes[] = '<a href="./m.php?frm=system&mdl=debug&do=info&classes=yes&cls='.$class_name.'#'.$class_name.'">'.$class_name.'</a>';
			}
		}
		return self::$classes;
	}

	// 获取函数详细信息
	public static function get_func_info($function_name){
		if(!empty(self::$function[$function_name])){
			return self::$function[$function_name];
		}
		if(!function_exists($function_name)){
			self::$function[$function_name] = 'not exist';
			return self::$function[$function_name];
		}
		$rf = new ReflectionFunction($function_name);
		$objParams = $rf->getParameters();
		$param_arr = array('__NUM__' => $rf->getNumberOfParameters().', '.$rf->getNumberOfRequiredParameters());
		$param_str_arr = array();
		if(!empty($objParams)){
			foreach($objParams as $param){
				$default = '';
				if($param->isOptional()){
					if(!$rf->isInternal())$default = $param->getDefaultValue();
					if(empty($default)){
						if(is_array($default)){
							$default = "array()";
						}else{
							if(is_numeric($default)){
								$default = '0';
							}else{
								$default = "''";
							}
						}
					}else{
						$default = htmlspecialchars(str_replace('Array(', 'array(', preg_replace('/\s+/i', '', $default)), ENT_QUOTES);
					}
				}
				if($param->isArray()){
					$default .= '<array>';
				}
				
				$param_arr[$param->getName()] = $default;
				$param_str_arr[] = '$'.$param->getName().($default === '' ? '' : ' = '.$default);
			}
		}
		self::$function[$function_name] = array(
			'file'		=> $rf->getFileName().'&nbsp;'.$rf->getStartLine().'~'.$rf->getEndLine().'<a name="'.$rf->getName().'">&nbsp;</a>',
			'name'		=> $rf->getName().'('.implode(', ', $param_str_arr).')',
			'user'		=> $rf->isUserDefined() ? 'yes' : 'no',
			'doc'		=> $rf->getDocComment(),
			'params'	=> $param_arr,
		);
		return self::$function[$function_name];
	}

	// 获取类详细信息
	public static function get_class_info($class_name){
		if(!empty(self::$class[$class_name])){
			return self::$class[$class_name];
		}
		if(!class_exists($class_name)){
			self::$class[$class_name] = 'not exist';
			return self::$class[$class_name];
		}
		$rc = new ReflectionClass($class_name);
		$objProperties = $rc->getProperties();
		$property_arr = array();
		if(!empty($objProperties)){
			foreach($objProperties as $property){
				$modify = '';
				if($property->isPublic()){
					$modify = 'public&nbsp;';
				}else{
					if($property->isPrivate()){
						$modify = 'private&nbsp;';
					}else{
						if($property->isProtected()){
							$modify = 'protected&nbsp;';
						}
					}
				}
				$static = $property->isStatic() ? 'static&nbsp;' : '';
				$property_arr[] = $modify.$static.'$'.$property->getName();
			}
		}
		$objMethods = $rc->getMethods();
		$method_arr = array('__NUM__' => count($objMethods));
		if(!empty($objMethods)){
			foreach	($objMethods as $method){
				$modify = '';
				if($method->isPublic()){
					$modify = 'public&nbsp;';
				}else{
					if($method->isPrivate()){
						$modify = 'private&nbsp;';
					}else{
						if($method->isProtected()){
							$modify = 'protected&nbsp;';
						}
					}
				}
				$static = $method->isStatic() ? 'static&nbsp;' : '';
				$objParams = $method->getParameters();
				$param_str_arr = array();
				if(!empty($objParams)){
					foreach($objParams as $param){
						$default = '';
						if($param->isOptional()){
							$default = $param->getDefaultValue();
							if(empty($default)){
								if(is_array($default)){
									$default = "array()";
								}else{
									if(is_numeric($default)){
										$default = '0';
									}else{
										$default = "''";
									}
								}
							}else{
								$default = htmlspecialchars(str_replace('Array(', 'array(', preg_replace('/\s+/i', '', $default)), ENT_QUOTES);
							}
							$default = ' = '.$default;
						}
						$param_str_arr[] = '$'.$param->getName().$default;
					}
				}
				$method_arr[] = '<a href="./m.php?frm=system&mdl=debug&do=info&cls='.$class_name.'&method='.$method->name.'#'.$method->name.'">'.$modify.$static.$method->name.'('.implode(', ', $param_str_arr).')</a>'.($method->isInternal() ? '&nbsp;&lt;internal&gt;' : '');
			}
		}
		$parent = $rc->getParentClass();
		self::$class[$class_name] = array(
			'file'		=> $rc->getFileName().'&nbsp;'.$rc->getStartLine().'~'.$rc->getEndLine().'<a name="'.$rc->getName().'">&nbsp;</a>',
			'name'		=> $rc->getName(),
			'user'		=> $rc->isUserDefined() ? 'yes' : 'no',
			'doc'		=> $rc->getDocComment(),
			'parent'	=> empty($parent) ? '' : '<a href="./m.php?frm=system&mdl=debug&do=info&cls='.$parent->name.'#'.$parent->name.'">'.$parent->name.'</a>',
			'properties'=> $property_arr,
			'constructor'	=> $rc->getConstructor()->name,
			'methods'	=> $method_arr,
			
		);
		
		return self::$class[$class_name];
	}

	public static function get_method_info($class_name, $method_name){
		if(empty($class_name) || empty($method_name)){
			return '';
		}
		if(!class_exists($class_name)){
			self::$class[$class_name] = 'not exist';
			return self::$class[$class_name];
		}
		$methods = get_class_methods($class_name);
		if(!in_array($method_name, $methods)){
			self::$method[$method_name] = 'not exist';
			return self::$method[$method_name];
		}
		if(!empty(self::$method[$method_name])){
			return self::$method[$method_name];
		}
		$rm = new ReflectionMethod($class_name, $method_name);
		$objParams = $rm->getParameters();
		$param_arr = array('__NUM__' => $rm->getNumberOfParameters().', '.$rm->getNumberOfRequiredParameters());
		$param_str_arr = array();
		if(!empty($objParams)){
			foreach($objParams as $param){
				$default = '';
				if($param->isOptional()){
					$default = $param->getDefaultValue();
					if(empty($default)){
						if(is_array($default)){
							$default = "array()";
						}else{
							if(is_numeric($default)){
								$default = '0';
							}else{
								$default = "''";
							}
						}
					}else{
						$default = htmlspecialchars(str_replace('Array(', 'array(', preg_replace('/\s+/i', '', $default)), ENT_QUOTES);
					}
				}
				if($param->isArray()){
					$default .= '<array>';
				}
				
				$param_arr[] = $default;
				$param_str_arr[] = '$'.$param->getName().($default === '' ? '' : ' = '.$default);
			}
		}
		$modify = '';
		if($rm->isPublic()){
			$modify = 'public&nbsp;';
		}else{
			if($rm->isPrivate()){
				$modify = 'private&nbsp;';
			}else{
				if($rm->isProtected()){
					$modify = 'protected&nbsp;';
				}
			}
		}
		$static = $rm->isStatic() ? 'static&nbsp;' : '';
		self::$method[$method_name] = array(
			'file'		=> $rm->getFileName().'&nbsp;'.$rm->getStartLine().'~'.$rm->getEndLine().'<a name="'.$rm->getName().'">&nbsp;</a>',
			'name'		=> $modify.$static.$rm->getName().'('.implode(', ', $param_str_arr).')',
			'class'		=> '<a href="./m.php?frm=system&mdl=debug&do=info&cls='.$rm->getDeclaringClass()->name.'#'.$rm->getDeclaringClass()->name.'">'.$rm->getDeclaringClass()->name.'</a>',
			'user'		=> $rm->isUserDefined() ? 'yes' : 'no',
			'doc'		=> $rm->getDocComment(),
			'params'	=> $param_arr,
		);
		return self::$method[$method_name];
	}

	public static function get_extension_loaded(){
		if(!empty(self::$exts)){
			return self::$exts;
		}
		$exts = get_loaded_extensions();
		foreach($exts as $ext){
			self::$exts[] = '<a href="./m.php?frm=system&mdl=debug&do=info&exts=yes&ext='.$ext.'#'.$ext.'">'.$ext.'</a>';
		}
		return self::$exts;
	}

	public static function get_extension_info($ext_name){
		if(!extension_loaded($ext_name)){
			self::$ext = 'no loaded';
			return self::$ext;
		}
		$re = new ReflectionExtension($ext_name);
		$objFuncs = $re->getFunctions();
		$func_arr = array();
		if(!empty($objFuncs)){
			foreach($objFuncs as $rf){
				$function_name = $rf->getName();
				$func_arr[] = '<a href="./m.php?frm=system&mdl=debug&do=info&exts=yes&ext='.$ext_name.'&fn='.$function_name.'#'.$function_name.'">'.$function_name.'()</a>';
			}
		}
		$objClasses = $re->getClasses();
		$classes_arr = array();
		if(!empty($objClasses)){
			foreach($objClasses  as $rc){
				$ext_name = $rc->getName();
				$ext_name = $rc->getName();
				$classes_arr[] = '<a href="./m.php?frm=system&mdl=debug&do=info&exts=yes&ext='.$ext_name.'&cls='.$ext_name.'#'.$ext_name.'">'.$ext_name.'</a>';
			}
		}
		self::$ext = array(
			'name'		=> $ext_name.'<a name="'.$ext_name.'">&nbsp;</a>',
			'version'	=> $re->getVersion(),
			'consts'	=> $re->getConstants(),
			'funcs'		=> $func_arr,
			'classes'	=> $classes_arr,
			'ini'		=> $re->getINIEntries(),
		);
		return self::$ext;
	}
}
?>